Skip to content

docs(pm-dispatch): six protocol-line repairs, line-neutral on both governed text surfaces - #16339

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-16004-skill-protocol-lines
Sep 7, 2026
Merged

docs(pm-dispatch): six protocol-line repairs, line-neutral on both governed text surfaces#16339
os-zhuang merged 2 commits into
mainfrom
claude/issue-16004-skill-protocol-lines

Conversation

@os-steve

@os-steve os-steve commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator

Fixes #16004
Fixes #16064
Fixes #15897
Fixes #15961
Refs #15975
Refs #14768

Six protocol-line repairs on the two governed pm-dispatch text surfaces. No code, no
behaviour: these files are read in full by every seat session, and each repaired line was
measured to be producing wrong runs.

Both files are LINE-NEUTRAL — every added line is paid by a fold inside the same
section, never by a ceiling raise:

file lines widest table row
.claude/skills/pm-dispatch/SKILL.md 811 / 811 (headroom 0) 342 / 342 (headroom 0)
.claude/skills/pm-dispatch/references/core-rules.md 150 / 150 (headroom 0) 0 / 0

Every added line is ≤ 119 bytes against the 120-byte rule. The four-axis decision-frame
block in SKILL.md is untouched, and check:skill-frame-sync confirms the two copies are
still structurally isomorphic.

What changed, per card

#16064 — SKILL.md:538 ordered every dispatch to demand a second claim comment

AGENTS.md:400 binds a dispatched executor to post no second claim; SKILL.md:538
ordered the PM to demand one. The skill's own tiebreak makes AGENTS.md the winner, so
:538 was the defective line. Five devs across two repos hit it; four refused, one complied
— identical orders, opposite outcomes.

Rewritten in place, 1:1, to the AGENTS.md reading: the dispatch states the dev posts no
second claim, the PM's Claim: is its identity, and the dev verifies the newest one names
its branch and stops with a report on a mismatch.

⚠️ Worth a reviewer's eye: the triage comment on #16064 also named SKILL.md:479
(家族派发的折叠认领) as a second site ordering a claim per member card. Reading that line in
its block (467–485), its subject is the PM's atomic pair, not the dev — it describes the
PM's own folded claims across member cards, which is what this flight's own claims are. It
therefore does not carry the same defect and is left untouched. Flagging the reading rather
than acting on it, since it differs from the triage note.

#15897 — the dispatch asked for the human-readable gate list and got it scraped

The old line named a bare dispatch-gates.mjs run, whose prose output has to be
scraped; a dev's regex silently dropped the whole convention-triggered section at exit 0,
five gates with it, and CI went red on check:i18n.

Rewritten in place, 1:1, to name the machine form: take the list from
dispatch-gates.mjs --commands, run each command, land the exit code before any pipe, and
reconcile with --ran; never scrape the human-readable output. The reconciliation is what
now mechanically guarantees no family is missed, so it carries that guarantee instead of
prose (rules-only register).

#16004 — the seat mutex's reading 3 was blind to a queued card's branch

Reading 3 filtered on pm:dispatched only, so a session pushing to a pm:queue card's
claude/issue-N-* branch produced no reading at all; one collision was found by hand, off
the branch tip, not by the mutex.

Widened to two lines: the card set becomes pm:dispatchedpm:queue, and a branch push
since the last shift-end brief counts as a claim in its own right (one git ls-remote per
card) — a push is a claim, and owes the comment reading 3 counts.

Paid by folding the cross-seat-handwriting line and the readings-only-add-a-yield line into
one, inside the same block.

#15975 (Refs) — a single-carrier gate hang makes a clear indistinguishable from a strip

The clause-② gate is a dual carrier; hung on one side only, the eventual legitimate clear
can only ever produce the one-removal strip signature. The defect is committed at hang
time and only surfaces at landing.

One line added beside the existing carrier rule: a Clause-②: yes claim hangs the gate on
the card in the same write as the claim, and when the delivering PR opens the seat reads
check-clause2-carriers --pair N at exit 0 before requesting any review — so a split is
repaired at hang time, never at landing.

Paid by folding the --tier hint line and the enqueue-refusal line into one, inside the
same 复核 block. The other half of this card (the os-dev.md line) rides its own flight, so
this PR only refs it.

#14768 (Refs) — the unexecutable "report, then act" fence

SKILL.md:543 carried 「报备后」 — report for the record, then fix — which presupposes a
mid-run channel a one-shot dev does not have, and so hands it the whole three-way choice the
author thought they had fenced. This is the census's hit 3, in the allow-with-trace class.

Rewritten in place, 1:1, to the executable form: fix on the producer side and report the
landing point; never patch on the consumer side. Only the SKILL.md hit is in scope here —
the census's other three hits ride flight B.

#15961 — the core-rules digest owed the two decision-frame rules

One digest line added to the 升级与决策 block, in the digest's plain-language register: every
decision card and director presentation carries Governing text:, and the protocol is the
baseline — a spec-vs-code mismatch defaults to changing the code, and a protocol change is
its own card rather than an option on a defect card.

Paid by folding the two recommendation-order lines into one. ⚠️ The fold drops two clauses
that are derivable rather than independent — 「其余投不翻它」 (a consequence of the ≥50% weight
stated in the same line) and 「防错轴打破余下平局」. The second is a genuine rule and it is
not lost from the corpus: SKILL.md keeps it. It leaves the digest only, which is what a
fold in a digest costs.

Verification

Gate union run at d88c29c76a, this PR's head, after the final commit.

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 16
commands from the tree (never from a hand-written path list). Every one was run with its
exit code captured before any pipe, then reconciled:

✓ dispatch-gates --ran: 16 derived famil(ies) accounted for — 16 run, 0 NOT-MEASURED.

16 of 16 green. One needed a build first and is worth naming, because its first exit was not
a finding:

  • pnpm --filter @objectstack/lint run check:doc-formula-expressions first returned exit
    3
    — the gate's own PREREQUISITE-NOT-MET code, in its words "Nothing was measured … It is
    NOT a finding"
    . After turbo run build --filter=@objectstack/formula --filter=@objectstack/lint
    it re-ran at exit 0.

The dispatch-named gates, quoted from their own verdict lines rather than from a bare $?:

✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/SKILL.md is 811 lines (ceiling 811; headroom 0).
✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/SKILL.md: widest table row is 342 bytes (pin 342; headroom 0).
✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/core-rules.md is 150 lines (ceiling 150; headroom 0).
✓ check-skill-id-lint self-test: 14 cases pass.
✓ check-skill-id-lint: 25 file(s) clean (pattern /#[0-9]{3,}/g).
✓ check-skill-frame-sync self-test: 13 cases pass …
✓ check-skill-frame-sync: 2 copies of the decision frame are structurally isomorphic across 2 files
✓ check-governed-prose self-test: 28 cases pass.
✓ check-governed-prose: 2 instruction surface(s) name all 5 registered governed surfaces …
✓ check-governed-merges --self-test: 274 assertions …
✓ check-half-states self-test: 2535 cases pass.

check-governed-merges --test on this PR's real paths returns exit 3 — GOVERNED, as
expected for .claude/**:

governed-surface predicate: 2 of 2 path(s) hit the register (5 surfaces, repo-agnostic).
  ⛔  GOVERNED — a human merge is the review record for this PR (#9495 regime).

Whole-repo pnpm lint (eslint . --no-inline-config) ran in full through
scripts/pm/os-verify-lock.sh (slot issue-16004) and returned:

os-verify-lock: VERDICT command-exit 0 · held the lock 116s (1m56s) · waited 0s

No narrowing was taken, so no narrowing needs declaring.

H-row check. Each of the 10 sentences this diff removes was grepped over scripts/ and
.claude/hooks: 0 hits, with a positive control proving the grep reaches that corpus
(scripts/pm/check-half-states.mjs does quote SKILL.md-register phrases, just not these).
No patrol row pins a sentence this PR rewrites.

维护者速读(草稿)

一、这次动的是什么。 只改两份 PM 协议文本,不动任何代码、不动任何行为。改的是六条把
派发跑错的规则行:每条要么在实测中直接产生了错误的运行,要么让一次合法操作变得无法自证。
两份文件都严格行数不变——新增的每一行都由同一段落里的一次合并偿还,没有抬任何天花板。

二、最贵的一条是"第二条认领"。 协议要求每份派发令命令 dev 再发一条认领评论,而仓库根
的 AGENTS.md 明令 dev 不得再发。两处相互矛盾,而 AGENTS.md 按规则获胜。代价是实测出来的:
跨两个仓、两条车道,五个 dev 撞上同一条矛盾指令,四个拒绝执行、一个照做——同样的命令,相反
的结果。真正的成本不是那四次拒绝,而是那些默默挑一边、没人看见的运行。

三、门禁清单被当成散文抓取。 派发令原来让 dev 跑工具的"给人看"的那种输出,再用正则去
抓。一个 dev 的正则静默丢掉了整整一段(五个门禁),退出码仍是 0,读起来像跑完了,直到 CI 变
红。现在派发令点名机器可读形式,并要求逐条跑、退出码先落盘、再用工具自己的对账模式核。

四、两处让"证据"失效的机制。 其一,开轮互斥的第三个读数只看已派发的卡,于是有人在排队
卡的分支上干活时它一个读数都产生不了——实测撞过一次车,是靠人读分支尖端发现的,不是靠互斥。
现在分支推送本身即认领。其二,契约复审的门禁标签本该同时挂在卡和 PR 两处,只挂一处时,日后
那次合法的清除只会留下"被剥离"的签名——缺陷在挂标那一刻就已铸成,却要到落地才暴露。现在挂
标即同笔挂卡,并在 PR 开出时先对账。

五、剩下两条是收口。 一条把"先报备、再动手"这种一次性 dev 根本没有通道执行的围栏,改成
本轮内能闭合的形式;一条把决策框架的两条新规则补进核心条款摘要,让摘要和主协议不再各说各话。
需要维护者留意的是第六条的合并代价:摘要里少了一句"防错轴打破余下平局"——该规则在主协议
SKILL.md 中完整保留,只是不再在摘要中重复。

席位意见:


🤖 Generated with Claude Code

Generated by Claude Code


Generated by Claude Code

- reading 3 counts `pm:dispatched` u `pm:queue` and a branch push (a push is
  a claim and owes the comment), paid by folding the cross-seat/readings pair
- the dispatch names `dispatch-gates.mjs --commands`, exits captured before
  any pipe, `--ran` reconciling; the human-readable form is never scraped
- the dispatch tells the dev it posts no second claim, per AGENTS.md
- the producer-side fence made executable: fix and report, no notify-then-act
- a `Clause-<2>: yes` claim hangs the gate on the card in the same write and
  reads `--pair N` before requesting review, paid by folding the tier pair
- core-rules digest gains the `Governing text:` + protocol-baseline line,
  paid by folding the two recommendation-order lines

SKILL.md 811/811, table pin 342 untouched; core-rules.md 150/150.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation labels Sep 6, 2026
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 6, 2026
This was referenced Sep 6, 2026
@claude

claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

ACCEPT — contract-tier review of PR #16339, head d88c29c76a (skills seat, 2026-09-06T15:1xZ).

Implemented-by: claude/issue-16004-skill-protocol-lines (os-dev subagent, opus under the measured quota exemption recorded on #16004 and #14768 at 14:05Z)
Reviewed-by: session_019RfFHiRCSs3JXLK4cwcfox (skills seat)

Verified in a detached compare worktree at the PR head, not from the report:

Ruling on the open question — A. SKILL.md's 「家族派发的折叠认领:共享分支按链首卡命名;每张成员卡各留认领评论并点名该分支」 sits in the PM's atomic-pair block (its neighbours are 「派发前按序执行原子对」 and 「② 认领评论(英文)」) and orders the PM's folded claim per member card — exactly what this flight's six claims are. It states nothing AGENTS.md contradicts and is not copied into dispatch orders, so it is not the defect #16064 measured; no edit, and no follow-up card for a subject marker — the block's subject is explicit two lines above.

Collision, recorded for the approvers: the devx seat's draft PR #16271 (the #14944 depth-hold rules) edits the same two files; git merge-tree between the two heads conflicts in SKILL.md's 候选与批次 block. Neither waits for the other; whichever merges second owes a patch round that merges main, re-runs the line ratchet live and re-folds (seat note 5560027553 on that PR).

Landing regime: governed (.claude/**) ⇒ the PR stays a draft; reviewers os-zhuang + hotlong requested in this same act, needs-user-decision added, the final 维护者速读 posted as the next comment; human merge. On the merge: #16004 · #16064 · #15897 · #15961 close by Fixes; #15975 and #14768 stay pm:dispatched for flight B.


Generated by Claude Code

@claude
claude Bot requested review from hotlong and os-zhuang September 6, 2026 15:07
@claude

claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

维护者速读

事情:只改两份 PM 协议文本(SKILL.md 与核心条款摘要),不动代码、不动行为。改的是六条实测把派发跑错的规则行,两份文件严格行数不变——新增的每一行都由同段落一次合并偿还,没有抬任何天花板。

最贵的一条是「第二条认领」:协议原来要求每份派发令命令 dev 再发一条认领评论,而仓库根 AGENTS.md 明令 dev 不得再发。跨两仓两车道五个 dev 撞上这条矛盾指令,四个拒绝、一个照做。现在协议改成 AGENTS.md 的读法:PM 那条认领就是 dev 的身份,dev 只核对最新一条点名自己的分支。

门禁清单不再靠人读输出:派发令原来让 dev 抓工具「给人看」的输出,一个 dev 的正则静默丢了五个门禁、退出码仍是 0。现在点名机器可读形式,逐条跑、退出码先落盘、再用 --ran 对账。

两处让证据失效的机制补上:开轮互斥的第三个读数原来只看已派发的卡,有人在排队卡的分支上干活时它读不到——现在分支推送本身即认领;契约复审标签原来可以只挂 PR 不挂卡,日后合法清除就留下「被剥离」的假签名——现在挂标同笔挂卡,PR 开出即对账。另两条是收口:「先报备再动手」改成一次性 dev 能闭合的形式;决策框架的两条新规则补进摘要。

要请您留意的:摘要里少了「防错轴打破余下平局」这半句,规则本体在 SKILL.md 四轴段完整保留(席位逐句核过),只是摘要不再重复。另外 devx 席的 PR #16271 改同一段落,两份草案互相冲突,后合的一方补一轮合并,不影响本 PR。

席位意见:建议合并。四张卡由本 PR 关闭(#16004 · #16064 · #15897 · #15961),#15975#14768 的另一半在 flight B 的 os-dev.md 里。


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review September 7, 2026 00:49
@os-zhuang
os-zhuang enabled auto-merge September 7, 2026 00:49
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 7, 2026
Merged via the queue into main with commit 8da8d50 Sep 7, 2026
35 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-16004-skill-protocol-lines branch September 7, 2026 01:18
os-zhuang pushed a commit that referenced this pull request Sep 7, 2026
The merge of origin/main brought SKILL.md to 813 lines against a ceiling of
811: both sides were line-neutral against the merge base, but the folds this
branch used to pay for its four depth-hold lines landed in regions main had
re-folded independently, so the resolution kept both. Pay the +2 with two more
same-topic folds inside the same file — no rule removed, no ceiling raised, no
cross-file move:

- the two seat invariants "循环必须能从全新会话恢复" and "PM 不写文件、不写代码"
  join on one line (112 bytes); the separator before 唯一例外 drops from ; to ,
  so the exception still reads as the no-writing rule's, not the recovery one's.
- the two conditional-clause items 拒收用例 and 过滤/谓词语义 join on one line
  (119 bytes) inside the enumeration they already belong to.

Ratchet reads SKILL.md 811/811 headroom 0, widest table row 342 (pin 342),
core-rules.md 150/150. Every prose line stays within the 120-byte budget.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TezFG8ZMrNH6n5VTNpPpdH
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment